// ----------------------------------------------------------------------------
// atomic_intrinsic.h
// ----------------------------------------------------------------------------
/*
 Description:
 
 低レベルなアトミック処理関数群. (32bit値と64bit値のみ対応)
 
 ----------------------------------------------------------------
 使い方.
 
 利用方法は各関数のコメントを参照すること.
 */
#pragma once
#include <fw/base/core/macros.h>
#include <fw/base/core/stdinteger.h>

#if   defined(FW_TARGET_WINDOWS)
#include <fw/base/concurrent/_Windows/atomic_intrinsic.windows.h>
#elif defined(FW_TARGET_APPLE)
#include <fw/base/concurrent/_MacOSX/atomic_intrinsic.apple.h>
#else
#error	 "未対応のプラットフォームです."
#endif

/**
 * 32bit値の排他的な値の代入.
 * 
 * @param ptr    [in]  排他的に値を代入するデータへのポインタ.
 * @param value  [in]  設定する値.
 * 
 * @return 代入前の値を返します.
 */
FW_FORCE_INLINE int32_t FwAtomicSet( volatile int32_t* ptr, int32_t value )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_SET(ptr,value);
}

/**
 * 32bit値の排他的な値の取得. 
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return 排他的に取得した32bit値を返します. 
 */
FW_FORCE_INLINE int32_t FwAtomicGet( volatile int32_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_GET(ptr);
}

/**
 * 32bit値の排他的な値のCAS（比較と代入）操作.
 * 
 * @param ptr     [in]  値へのポインタ.
 * @param compare [in]  比較値.
 * @param swap    [in]  比較に成功した場合、代入する値.
 * 
 * @return 代入前の値を返す. 
 */
FW_FORCE_INLINE int32_t FwAtomicCas( volatile int32_t* ptr, int32_t compare, int32_t swap )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_CAS(ptr,compare,swap);
}

/**
 * 32bit値の排他的な値のインクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return インクリメント後の32bit値を返します.
 */
FW_FORCE_INLINE int32_t FwAtomicIncrement( volatile int32_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_INC(ptr);
}

/**
 * 32bit値の排他的な値のインクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return インクリメント前の32bit値を返します.
 */
FW_FORCE_INLINE int32_t FwAtomicIncrement_PreValue( volatile int32_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_INC_PREVALUE(ptr);
}

/**
 * 32bit値の排他的な値のデクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return デクリメント後の32bit値を返します.
 */
FW_FORCE_INLINE int32_t FwAtomicDecrement( volatile int32_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_DEC(ptr);
}

/**
 * 32bit値の排他的な値のデクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return デクリメント前の32bit値を返します.
 */
FW_FORCE_INLINE int32_t FwAtomicDecrement_PreValue( volatile int32_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_DEC_PREVALUE(ptr);
}

/**
 * 32bit値の排他的な値の加算.
 * 
 * @param ptr    [in]  値へのポインタ.
 * @param value  [in]  加算する値.
 * 
 * @return 加算前の32bit値を返します.
 */
FW_FORCE_INLINE int32_t FwAtomicAdd( volatile int32_t* ptr, int32_t value )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_ADD(ptr,value);
}
#if defined(FW_TARGET_64BIT)
/**
 * 64bit値の排他的な値の代入.
 * 
 * @param ptr    [in]  排他的に値を代入するデータへのポインタ.
 * @param value  [in]  設定する値.
 * 
 * @return 代入前の値を返します.
 */
FW_FORCE_INLINE int64_t FwAtomicSet64( volatile int64_t* ptr, int64_t value )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_SET64(ptr,value);
}

/**
 * 64bit値の排他的な値の取得.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return 排他的に取得した64bit値を返します.
 */
FW_FORCE_INLINE int64_t FwAtomicGet64( volatile int64_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_GET64(ptr);
}

/**
 * 64bit値の排他的な値のCAS（比較と代入）操作.
 * 
 * @param ptr     [in]  値へのポインタ.
 * @param compare [in]  比較値.
 * @param swap    [in]  比較に成功した場合、代入する値.
 * 
 * @return 代入前の値を返す.
 */
FW_FORCE_INLINE int64_t FwAtomicCas64( volatile int64_t* ptr, int64_t compare, int64_t swap )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_CAS64(ptr,compare,swap);
}

/**
 * 64bit値の排他的な値のインクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return インクリメント後の64bit値を返します.
 */
FW_FORCE_INLINE int64_t FwAtomicIncrement64( volatile int64_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_INC64(ptr);
}

/**
 * 64bit値の排他的な値のインクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return インクリメント前の64bit値を返します.
 */
FW_FORCE_INLINE int64_t FwAtomicIncrement_PreValue64( volatile int64_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_INC_PREVALUE64(ptr);
}

/**
 * 64bit値の排他的な値のデクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return デクリメント後の64bit値を返します.
 */
FW_FORCE_INLINE int64_t FwAtomicDecrement64( volatile int64_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_DEC64(ptr);
}

/**
 * 64bit値の排他的な値のデクリメント.
 * 
 * @param ptr    [in]  値へのポインタ.
 * 
 * @return デクリメント前の64bit値を返します.
 */
FW_FORCE_INLINE int64_t FwAtomicDecrement_PreValue64( volatile int64_t* ptr )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_DEC_PREVALUE64(ptr);
}

/**
 * 64bit値の排他的な値の加算.
 * 
 * @param ptr    [in]  値へのポインタ.
 * @param value  [in]  加算する値.
 * 
 * @return 加算前の64bit値を返します.
 */
FW_FORCE_INLINE int64_t FwAtomicAdd64( volatile int64_t* ptr, int64_t value )
{
	return FW_ATOMIC_CORE_IMPL_ATOMIC_ADD64(ptr,value);
}
#endif // FW_TARGET_64BIT 
